import java.io.File

fun main() {

    // +"Derry"

    val names = listOf("Derry1", "Derry2", "Derry3") // 集合

    val result =
       html {
            // this == 第一个中转站 { head body 。。 }
            head {
                // this == head中转站 { title }
                title { +"使用 Kotlin 进行 HTML 编码" }
            }
            body {
                // this == body中转站 { h1 p a p }
                h1 {
                    // this == h1中转站 { 未知 }
                }
                p { -"此格式可用作 HTML 的替代标记" }

                // 具有属性和文本内容的元素
                a(href = "http://bbs.xiangxueketang.cn/pins/recommended") { -"享学论坛" }

                // 混合内容
                p {
                    -"Derry老师来了"
                    b { -"Derry是谁" }
                    -"文本。有关更多信息，请参阅"
                    a(href = "http://www.xiangxueketang.cn/") { -"湖南享学" }
                    -"Derry的项目"
                }
                p { -"一些文字" }

                // 从命令行参数生成的内容
                p {
                    -"命令行参数是："
                    ul {
                        // this == UL中转站 { li 子标签  }
                        for (name in names)
                            li { -name } // this == LI中转站
                    }
                }
            }
        }
    println(result)
    val file = File("DDD.html")
    file.writeText(result.toString())
}

private class Html : TagClass("html") {
    fun head(action: Head.() -> Unit) {
        val newHead = Head()
        newHead.action()
        elements += newHead
    }

    fun body(action: Body.() -> Unit) {
        val newBody = Body("body")
        newBody.action()
        elements+=newBody
    }
}

private class Head : TagClass("head") {
    fun title(action: Title.() -> Unit) {
        val newTitle = Title()
        newTitle.action()
        elements.add(newTitle)
    }
}

private class Title : TagClass("title")
private class H1 : Body("h1")
private class P : Body("p")
private class A : Body("a") {
    var href: String
        get() = attributes["href"]!!// !! 我断言你可以拿到
        set(value) {
            attributes["href"] = value
        }
}

private class LI : Body("li")
private class UL : Body("ul") {
    fun li(action: LI.() -> Unit) {
        val newLi = LI()
        newLi.action()
        elements.add(newLi)
    }
}

private class B : Body("b")

private open class Body(tagName: String) : TagClass(tagName = tagName) {
    fun h1(action: H1.() -> Unit) {
        val newH1 = H1()
        newH1.action()
        elements += newH1
    }

    fun p(action: P.() -> Unit) {
        val p = P()
        p.action()
        elements += p
    }

    fun a(href: String, action: A.() -> Unit) {
        val newA = A()
        newA.href = href
        newA.action()
        elements += newA
    }

    fun ul(action: UL.() -> Unit) {
        val newUl = UL()
        newUl.action()
        elements += newUl
    }

    fun b(action: B.() -> Unit) {
        val newB = B()
        newB.action()
        elements += newB
    }
}


private fun html(action: Html.() -> Unit): Html {
    val html = Html()
    html.action()
    return html
}

private interface Element {
    /**
     * @builder 拼杨门女将所有的元素
     * @indent 缩进效果
     */
    fun run(builder: StringBuilder, indent: String)


}

//text
// 文本的Element，独立的字符串
private class TextElement(val text: String) : Element {
    override fun run(builder: StringBuilder, indent: String) {
        // 缩进后，显示文本内容
        builder.append("$indent$text\n")
    }
}

//开始复杂

private open class Tag(val tagName: String) : Element {
    //    // 集合 每一个元素 都是 Element
    val elements = arrayListOf<Element>()
    // Map集合 每一个元素 Key=属性名  Value=属性对应的值
    val attributes = hashMapOf<String, String>()

    override fun run(builder: StringBuilder, indent: String) {
        builder.append("$indent<$tagName${renderAttributes()}>\n")
        for (element in elements) {
            element.run(builder, "$indent---")
        }
        builder.append("$indent</$tagName>\n")
    }

    private fun renderAttributes(): String? {
        val builder = StringBuilder()
        for (key in attributes.keys) {
            builder.append("$key=\"${attributes[key]}\"")
        }
        return builder.toString()
    }

    override fun toString(): String {
        val builder = StringBuilder()
        // 参数一：StringBuilder方便组装html数据，  参数二：indent不要缩进
        run(builder, "")
        return builder.toString()
    }
}

private open class TagClass(tagName: String) : Tag(tagName = tagName) {
    operator fun String.unaryPlus() {// 运算符重载 +
        elements.add(TextElement(this))
    }

    operator fun String.unaryMinus() {// 运算符重载 -
        elements += TextElement(this)
    }
}